package blue.mqtt4j.internal.client.handler;

import blue.mqtt4j.client.MqttOptions;
import blue.mqtt4j.internal.client.net.NettyClient;
import io.netty.channel.Channel;
import io.netty.handler.codec.mqtt.MqttMessage;
import io.netty.handler.codec.mqtt.MqttMessageType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Jin Zheng
 * @since 1.0 2020-10-19
 */
public class MessageHandlerFactory
{
	private static Logger logger = LoggerFactory.getLogger(MessageHandlerFactory.class);

	private final Map<MqttMessageType, MessageHandler<? extends MqttMessage>> handlerMap = new HashMap<>();

	public MessageHandlerFactory(NettyClient client, MqttOptions options)
	{
		handlerMap.put(MqttMessageType.PUBLISH, new PublishMessageHandler(client));
		handlerMap.put(MqttMessageType.PUBACK, new PubAckMessageHandler(client));
		handlerMap.put(MqttMessageType.PUBREC, new PubRecMessageHandler(client));
		handlerMap.put(MqttMessageType.PUBREL, new PubRelMessageHandler(client));
		handlerMap.put(MqttMessageType.PUBCOMP, new PubCompMessageHandler(client));
		handlerMap.put(MqttMessageType.SUBACK, new SubAckMessageHandler(client));
		handlerMap.put(MqttMessageType.UNSUBACK, new UnsubAckMessageHandler(client));
	}

	public void handle(MqttMessage message, Channel channel)
	{
		MqttMessageType type = message.fixedHeader().messageType();
		MessageHandler<MqttMessage> handler = (MessageHandler<MqttMessage>)handlerMap.get(type);
		if (handler == null)
		{
			logger.error("No MessageHandler, type: {}", type);
			return;
		}
		logger.debug("Found {}, type: {}", handler.getClass().getSimpleName(), type);
		try
		{
			handler.handle(message, channel);
		}
		catch (Exception e)
		{
			logger.error("MessageHandler failure, ", e);
		}
	}


}

